{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 深入生命周期\n",
    "\n",
    "- https://course.rs/advance/lifetime/advance.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**TL;DR：深入理解 Rust 生命周期的高级要点**\n",
    "\n",
    "- 编译器的生命周期推断偶尔不够智能，会把 `&mut` 借用“看得”太远，导致明明安全的代码无法编译；需要调整代码结构或等待未来改进。\n",
    "- 某些模式（如 `match` 中的 `get_mut`、闭包的返回引用）会触发借用冲突，因为生命周期消除规则对闭包、复杂控制流支持有限；可改写为函数或分离作用域。\n",
    "- `unsafe` 解引用裸指针会生成“无界生命周期”，要谨慎使用并尽量让输出生命周期与输入绑定，以免产生未受限制的引用。\n",
    "- 生命周期约束（`'a: 'b`、`T: 'a`）用来表达作用域长短关系，新版 Rust 会自动推断部分约束，但在复杂结构体/impl 中仍需显式声明。\n",
    "- 闭包与函数拥有不同的生命周期消除规则：函数自动推断单引用参数的返回生命周期，闭包不会；可通过显式使用 `Fn` trait 签名绕过。\n",
    "- NLL（非词法生命周期）让引用在“最后一次使用”后立即结束，大幅减少借用冲突；Polonius 项目未来可能进一步改进。\n",
    "- `Reborrow`（再借用）允许在不使用原借用的前提下衍生新的引用；一旦原借用在再借用存活期内被使用就会报错。\n",
    "- 额外的生命周期消除：`impl` 中可用匿名生命周期 `'_`，Rust 2018 起自动省略某些 `T: 'a` 约束。\n",
    "- 为避免生命周期过度延长，方法签名中可引入新生命周期参数（如 `get_interface<'b>(&'b mut self)`），避免与结构体的长生命周期绑定。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 不太聪明的生命周期检查"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 示例1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot borrow `foo` as immutable because it is also borrowed as mutable",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0502] Error:\u001b[0m cannot borrow `foo` as immutable because it is also borrowed as mutable",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_2:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m13 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100mf\u001b[0m\u001b[38;5;100mo\u001b[0m\u001b[38;5;100mo\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249md\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                 \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m mutable borrow occurs here",
      " \u001b[38;5;246m14 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mf\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m     \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m      \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m immutable borrow occurs here",
      " \u001b[38;5;246m15 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m{\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m?\u001b[0m\u001b[38;5;249m}\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68ml\u001b[0m\u001b[38;5;68mo\u001b[0m\u001b[38;5;68ma\u001b[0m\u001b[38;5;68mn\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                      \u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┬\u001b[0m\u001b[38;5;68m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                        \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m mutable borrow later used here",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Foo;\n",
    "\n",
    "impl Foo {\n",
    "    fn mutate_and_share(&mut self) -> &Self {\n",
    "        &*self\n",
    "    }\n",
    "    fn share(&self) {}\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut foo = Foo;\n",
    "    let loan = foo.mutate_and_share();\n",
    "    foo.share();\n",
    "    println!(\"{:?}\", loan);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 函数 `mutate_and_share` 接受 `&mut self` 却返回 `&Self`，在调用者看来只是想“先可变借用再不可变借用”。\n",
    "- Rust 的生命周期消除规则让 `&mut self` 和返回的引用共享同一生命周期（`'a`），于是编译器认为可变借用一直持续到 `loan` 被用完。\n",
    "- 在 `loan` 仍存活期间调用 `foo.share()`（创建新的不可变借用）违反了“可变借用与其他借用不可同时存在”的规则，触发编译错误。\n",
    "- 实际逻辑没问题，但由于当前生命周期推断不够精细，只能通过调整代码结构来规避；暂时无法靠编译器自动识别这种安全模式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 解决方式: 直接复用返回的引用\n",
    "\n",
    "#[derive(Debug)]\n",
    "struct Foo;\n",
    "\n",
    "impl Foo {\n",
    "    fn mutate_and_share(&mut self) -> &Self {\n",
    "        &*self\n",
    "    }\n",
    "    fn share(&self) {}\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut foo = Foo;\n",
    "    let loan = foo.mutate_and_share();\n",
    "    loan.share(); // 既然 mutate_and_share 返回了 &Foo，后续就用它来做所有只读访问，不再重新借用 foo 本体\n",
    "    println!(\"{:?}\", loan);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 示例2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot borrow `*map` as mutable more than once at a time",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0499] Error:\u001b[0m cannot borrow `*map` as mutable more than once at a time",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_6:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m 5 │\u001b[0m     \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mg\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249md\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;68m'\u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;249m'\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mH\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249mM\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249my\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m-\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;249m'\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                        \u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┬\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                         \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m lifetime `'m` defined here",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m10 │\u001b[0m \u001b[38;5;37m╭\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m▶\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;37mm\u001b[0m\u001b[38;5;37ma\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37mc\u001b[0m\u001b[38;5;37mh\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;54mm\u001b[0m\u001b[38;5;54ma\u001b[0m\u001b[38;5;54mp\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mg\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m_\u001b[0m\u001b[38;5;37mm\u001b[0m\u001b[38;5;37mu\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m&\u001b[0m\u001b[38;5;37mk\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37my\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m{\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                 \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                  \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m first mutable borrow occurs here",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;37m┆\u001b[0m   ",
      " \u001b[38;5;246m13 │\u001b[0m \u001b[38;5;37m│\u001b[0m   \u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;100mm\u001b[0m\u001b[38;5;100ma\u001b[0m\u001b[38;5;100mp\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mi\u001b[0m\u001b[38;5;37mn\u001b[0m\u001b[38;5;37ms\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37mr\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37mk\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37my\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mc\u001b[0m\u001b[38;5;37ml\u001b[0m\u001b[38;5;37mo\u001b[0m\u001b[38;5;37mn\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m,\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37mV\u001b[0m\u001b[38;5;37m:\u001b[0m\u001b[38;5;37m:\u001b[0m\u001b[38;5;37md\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37mf\u001b[0m\u001b[38;5;37ma\u001b[0m\u001b[38;5;37mu\u001b[0m\u001b[38;5;37ml\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                   \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                    \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m second mutable borrow occurs here",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;37m┆\u001b[0m   ",
      " \u001b[38;5;246m16 │\u001b[0m \u001b[38;5;37m├\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m▶\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m}\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m               ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m╰\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m returning this value requires that `*map` is borrowed for `'m`",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    },
    {
     "ename": "Error",
     "evalue": "cannot borrow `*map` as mutable more than once at a time",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0499] Error:\u001b[0m cannot borrow `*map` as mutable more than once at a time",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_6:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m 5 │\u001b[0m     \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mg\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249md\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;68m'\u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;249m'\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mH\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249mM\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249my\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mK\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m-\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;249m'\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mV\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                        \u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┬\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                         \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m lifetime `'m` defined here",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m10 │\u001b[0m \u001b[38;5;37m╭\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m▶\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;37mm\u001b[0m\u001b[38;5;37ma\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37mc\u001b[0m\u001b[38;5;37mh\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;54mm\u001b[0m\u001b[38;5;54ma\u001b[0m\u001b[38;5;54mp\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mg\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m_\u001b[0m\u001b[38;5;37mm\u001b[0m\u001b[38;5;37mu\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m&\u001b[0m\u001b[38;5;37mk\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37my\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m{\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                 \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                  \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m first mutable borrow occurs here",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;37m┆\u001b[0m   ",
      " \u001b[38;5;246m14 │\u001b[0m \u001b[38;5;37m│\u001b[0m   \u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;100mm\u001b[0m\u001b[38;5;100ma\u001b[0m\u001b[38;5;100mp\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mg\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m_\u001b[0m\u001b[38;5;37mm\u001b[0m\u001b[38;5;37mu\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m&\u001b[0m\u001b[38;5;37mk\u001b[0m\u001b[38;5;37me\u001b[0m\u001b[38;5;37my\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;37m.\u001b[0m\u001b[38;5;37mu\u001b[0m\u001b[38;5;37mn\u001b[0m\u001b[38;5;37mw\u001b[0m\u001b[38;5;37mr\u001b[0m\u001b[38;5;37ma\u001b[0m\u001b[38;5;37mp\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;37m)\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                   \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m                    \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m second mutable borrow occurs here",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;37m┆\u001b[0m   ",
      " \u001b[38;5;246m16 │\u001b[0m \u001b[38;5;37m├\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m▶\u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m \u001b[0m\u001b[38;5;37m}\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m│\u001b[0m               ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;37m╰\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m returning this value requires that `*map` is borrowed for `'m`",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#![allow(unused)]\n",
    "fn main() {\n",
    "    use std::collections::HashMap;\n",
    "    use std::hash::Hash;\n",
    "\n",
    "    fn get_default<'m, K, V>(map: &'m mut HashMap<K, V>, key: K) -> &'m mut V\n",
    "    where\n",
    "        K: Clone + Eq + Hash,\n",
    "        V: Default,\n",
    "    {\n",
    "        match map.get_mut(&key) {\n",
    "            // `map.get_mut(&key)` 在整个 `match` 期间借用了 `map`\n",
    "            // └── 可变借用：&'m mut HashMap<K, V>\n",
    "\n",
    "            Some(value) => value, // 借用仍然持有到 `match` 结束\n",
    "\n",
    "            None => {\n",
    "                map.insert(key.clone(), V::default());\n",
    "                //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
    "                //     尝试再次可变借用 `map`（插入操作需要 &mut HashMap）\n",
    "                //     但上一行 `map.get_mut(&key)` 的借用尚未结束 → E0499/E0502\n",
    "\n",
    "                map.get_mut(&key).unwrap()\n",
    "                // ^^^^^^^^^^^^^^^^^^^^^^^\n",
    "                // 再次尝试可变借用 `map`，仍与外层 `get_mut` 的借用冲突\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 无界生命周期"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "不安全代码(`unsafe`)经常会凭空产生引用或生命周期，这些生命周期被称为是 **无界(unbound)** 的。\n",
    "\n",
    "无界生命周期往往是在解引用一个裸指针(裸指针 raw pointer)时产生的，换句话说，它是凭空产生的，因为输入参数根本就没有这个生命周期："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "dereference of raw pointer is unsafe and requires unsafe block",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0133] Error:\u001b[0m dereference of raw pointer is unsafe and requires unsafe block",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_4:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;54m*\u001b[0m\u001b[38;5;54mx\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m      \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m       \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m dereference of raw pointer",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "fn f<'a, T>(x: *const T) -> &'a T {\n",
    "    &*x\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 参数 `x` 是一个裸指针，它并没有任何生命周期，\n",
    "// 然后通过 `unsafe` 操作后，它被进行了解引用，变成了一个 Rust 的标准引用类型，该类型必须要有生命周期，也就是 `'a`。\n",
    "fn f<'a, T>(x: *const T) -> &'a T {\n",
    "    unsafe {\n",
    "        &*x\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看出 `'a` 是凭空产生的，因此它是无界生命周期。这种生命周期由于没有受到任何约束，因此它想要多大就多大，这实际上比 `'static` 要强大。例如 `&'static &'a T` 是无效类型，但是无界生命周期 `&'unbounded &'a T` 会被视为 `&'a &'a T` 从而通过编译检查，因为它可大可小，就像孙猴子的金箍棒一般。\n",
    "\n",
    "我们在实际应用中，要尽量避免这种无界生命周期。最简单的避免无界生命周期的方式就是在函数声明中运用生命周期消除规则。**若一个输出生命周期被消除了，那么必定因为有一个输入生命周期与之对应**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> AI:\n",
    "\n",
    "在安全 Rust 中，每一个 `&T` 或 `&mut T` 的生命周期都必须**绑定（bound）**到某个现有的、受编译器追踪的借用上：\n",
    "- 它要么来自函数输入、要么来自某个更长寿命的局部变量、要么是 `'static` 数据。借用检查器会沿着这些来源推导出“这份引用最长能活多久”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生命周期约束 HRTB (Higher-Rank Trait Bounds)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生命周期约束跟特征约束类似，都是通过形如 `'a: 'b` 的语法，来说明两个生命周期的长短关系。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ['a: 'b](https://course.rs/advance/lifetime/advance.html#a-b)\n",
    "\n",
    "> AI:\n",
    "\n",
    "语法 `'<long>: '<short>` 表示：生命周期 `'<long>` **至少**与 `'<short>` 一样长（也可以说 `'long` *outlives* `'short`）。\n",
    "- 它常用于结构体或函数中，表示“这个引用（或类型）只能在某个更短的生命周期内使用，但需要依赖一个更长寿的资源”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设有两个引用 `&'a i32` 和 `&'b i32`，它们的生命周期分别是 `'a` 和 `'b`，若 `'a` >= `'b`，则可以定义 `'a:'b`，表示 `'a` 至少要活得跟 `'b` 一样久。\n",
    "- 使用了生命周期约束 `'b: 'a`，因此 `'b` 必须活得比 `'a` 久\n",
    "- 结构体中的 `s` 字段引用的值必须要比 `r` 字段引用的值活得要久"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct DoubleRef<'a,'b:'a, T> {\n",
    "    r: &'a T,\n",
    "    s: &'b T\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [T: 'a](https://course.rs/advance/lifetime/advance.html#t-a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 类型 `T` 必须比 `'a` 活得要久\n",
    "- 结构体字段 `r` 引用了 `T`，因此 `r` 的生命周期 `'a` 必须要比 `T` 的生命周期更短(被引用者的生命周期必须要比引用长)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// Rust 1.30 版本之前\n",
    "\n",
    "struct Ref<'a, T: 'a> {\n",
    "    r: &'a T\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 从 1.31 版本开始，编译器可以自动推导 `T: 'a` 类型的约束\n",
    "// `'a`：表示 `Ref<'a, T>` 保存的引用在 `'a` 生命周期内是有效的。编译器会确保 `Ref` 实例本身的存活时间不会超过 `'a`\n",
    "struct Ref<'a, T> {\n",
    "    r: &'a T\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 一个使用了生命周期约束的综合例子:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> AI评价这个例子不太好...."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### * HRTB 是什么？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**HRTB**（Higher-Rank Trait Bounds，高阶生命周期约束）并不是指 `'a: 'b` 这类“普通”生命周期比较，而是指形如 `for<'a> ...` 的约束，用来表达“对所有 `'a` 都成立”的 trait 实现。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn apply_to_all<F>(f: F)\n",
    "where\n",
    "    F: for<'a> Fn(&'a str), // 这里的 `for<'a>` 表示 `f` 必须能够接受任何生命周期的 `&str`，无论是临时字面量还是局部变量引用。\n",
    "{\n",
    "    let greeting = String::from(\"hello\");\n",
    "    f(&greeting);\n",
    "    f(\"world\");\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### * 视窗视图（Window View）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "假设我们想对一个缓冲区（`buffer`）创建一段视窗（`window`），这个视窗是缓冲区的一部分切片。我们的结构体需要同时记住：\n",
    "\n",
    "1. `backing`：整块缓冲区（生命周期较长）。\n",
    "2. `view`：缓冲区中的一段切片（生命周期较短，但不能超过缓冲区）。\n",
    "\n",
    "这就非常适合用 `<'short, 'long: 'short>` 来表达：`'long`（持有缓冲区的生命周期）必须比 `'short`（视窗切片的生命周期）长。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"bcd\"\n",
      "\"abcdef\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::ops::Range;\n",
    "\n",
    "/// 表示一个对“长寿”缓冲区的“短寿”视窗。\n",
    "struct Window<'short, 'long: 'short> {\n",
    "    view: &'short [u8],\n",
    "    backing: &'long [u8],\n",
    "}\n",
    "\n",
    "impl<'short, 'long: 'short> Window<'short, 'long> {\n",
    "    /// 在更长寿的 `backing` 上建立一个短寿命的 `view`。\n",
    "    fn new(backing: &'long [u8], range: Range<usize>) -> Self {\n",
    "        let view = &backing[range];\n",
    "        Window { view, backing }\n",
    "    }\n",
    "\n",
    "    fn view(&self) -> &'short [u8] {\n",
    "        self.view\n",
    "    }\n",
    "\n",
    "    fn backing(&self) -> &'long [u8] {\n",
    "        self.backing\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let data = Vec::from(\"abcdef\".as_bytes());\n",
    "    let entire_slice: &[u8] = &data;\n",
    "\n",
    "    // `'long` 绑定到 `entire_slice` 的生命周期；`'short` 则绑定到 `Window` 的存活时间\n",
    "    let window = {\n",
    "        let short_lived = &entire_slice[1..4]; // b\"bcd\"\n",
    "        Window::<'_, '_>::new(entire_slice, 1..4)\n",
    "        //     └───────── `'long` outlives `'short` 保证 `entire_slice` 的生命周期更长\n",
    "    };\n",
    "\n",
    "    println!(\"{:?}\", std::str::from_utf8(window.view()).unwrap());    // \"bcd\"\n",
    "    println!(\"{:?}\", std::str::from_utf8(window.backing()).unwrap()); // \"abcdef\"\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 闭包函数的消除规则"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 函数引用的生命周期全部体现在签名里，编译器可以轻松套用“同一个参数 → 同一个返回”的消除规则。\n",
    "- 闭包因为类型隐藏、可能捕获环境，推断难度大得多，默认不会把参数和返回值绑定到同一生命周期。\n",
    "- 如果确实需要“闭包返回其参数引用”，可以借助函数指针、`for<'a>` 的 HRTB 约束，或手写一个实现 `Fn` 的结构体，把这条约束明确告诉编译器。\n",
    "\n",
    "遇到这种情况，不妨换个思路：\n",
    "- 尽量写成函数指针或普通函数；\n",
    "- 或者像上面的 `promote` 一样，通过 trait bound 把正确的生命周期关系“写死”。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn fn_elision(x: &i32) -> &i32 { x }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "lifetime may not live long enough",
     "output_type": "error",
     "traceback": [
      "\u001b[31mError:\u001b[0m lifetime may not live long enough",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_5:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m1 │\u001b[0m \u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m|\u001b[0m\u001b[38;5;249mx\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54m&\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249m3\u001b[0m\u001b[38;5;249m2\u001b[0m\u001b[38;5;249m|\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m-\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100m&\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249m3\u001b[0m\u001b[38;5;249m2\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m{\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mx\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m}\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                           \u001b[38;5;54m┬\u001b[0m        \u001b[38;5;100m┬\u001b[0m      \u001b[38;5;68m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                           \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m let's call the lifetime of this reference `'1`",
      " \u001b[38;5;240m  │\u001b[0m                                    \u001b[38;5;100m│\u001b[0m      \u001b[38;5;68m│\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                                    \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m let's call the lifetime of this reference `'2`",
      " \u001b[38;5;240m  │\u001b[0m                                           \u001b[38;5;68m│\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                                           \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m returning this value requires that `'1` must outlive `'2`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "let closure_slision = |x: &i32| -> &i32 { x };"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 闭包依旧是闭包，只是我们告诉编译器：参数与返回值共享同一个生命周期 `'a`\n",
    "let closure_elision: Box<dyn for<'a> Fn(&'a i32) -> &'a i32> = Box::new(|x| x);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 用 Fn 特征解决闭包生命周期\n",
    "\n",
    "fn main() {\n",
    "   let closure_slision = fun(|x: &i32| -> &i32 { x });\n",
    "   assert_eq!(*closure_slision(&45), 45);\n",
    "   // Passed !\n",
    "}\n",
    "\n",
    "fn fun<T, F: Fn(&T) -> &T>(f: F) -> F {\n",
    "   f\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NLL (Non-Lexical Lifetime)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "之前我们在[引用与借用](https://course.rs/basic/ownership/borrowing.html#NLL)那一章其实有讲到过这个概念，简单来说就是：**引用的生命周期正常来说应该从借用开始一直持续到作用域结束**，但是这种规则会让多引用共存的情况变得更复杂："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello and hello\n",
      "hello\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{\n",
    "   let mut s = String::from(\"hello\");\n",
    "\n",
    "    let r1 = &s;\n",
    "    let r2 = &s;\n",
    "    println!(\"{} and {}\", r1, r2);\n",
    "    // 新编译器中，r1,r2作用域在这里结束\n",
    "\n",
    "    let r3 = &mut s;\n",
    "    println!(\"{}\", r3);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按照上述规则，这段代码将会报错，因为 `r1` 和 `r2` 的不可变引用将持续到 `main` 函数结束，而在此范围内，我们又借用了 `r3` 的可变引用，这违反了借用的规则：要么多个不可变借用，要么一个可变借用。\n",
    "\n",
    "好在，该规则从 1.31 版本引入 `NLL` 后，就变成了：**引用的生命周期从借用处开始，一直持续到最后一次使用的地方**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按照最新的规则，我们再来分析一下上面的代码。`r1` 和 `r2` 不可变借用在 `println!` 后就不再使用，因此生命周期也随之结束，那么 `r3` 的借用就不再违反借用的规则，皆大欢喜。\n",
    "\n",
    "再来看一段关于 `NLL` 的代码解释："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "let mut u = 0i32;\n",
    "let mut v = 1i32;\n",
    "let mut w = 2i32;\n",
    "\n",
    "// lifetime of `a` = α ∪ β ∪ γ\n",
    "let mut a = &mut u;     // --+ α. lifetime of `&mut u`  --+ lexical \"lifetime\" of `&mut u`,`&mut u`, `&mut w` and `a`\n",
    "use(a);                 //   |                            |\n",
    "*a = 3; // <-----------------+                            |\n",
    "...                     //                                |\n",
    "a = &mut v;             // --+ β. lifetime of `&mut v`    |\n",
    "use(a);                 //   |                            |\n",
    "*a = 4; // <-----------------+                            |\n",
    "...                     //                                |\n",
    "a = &mut w;             // --+ γ. lifetime of `&mut w`    |\n",
    "use(a);                 //   |                            |\n",
    "*a = 5; // <-----------------+ <--------------------------+"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这段代码一目了然，`a` 有三段生命周期：`α`，`β`，`γ`，每一段生命周期都随着当前值的最后一次使用而结束。\n",
    "\n",
    "在实际项目中，`NLL` 规则可以大幅减少引用冲突的情况，极大的便利了用户，因此广受欢迎，最终该规则甚至演化成一个独立的项目，未来可能会进一步简化我们的使用，`Polonius`：\n",
    "\n",
    "- [项目地址](https://github.com/rust-lang/polonius)\n",
    "- [具体介绍](http://smallcultfollowing.com/babysteps/blog/2018/04/27/an-alias-based-formulation-of-the-borrow-checker/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reborrow 再借用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "学完 `NLL` 后，我们就有了一定的基础，可以继续学习关于借用和生命周期的一个高级内容：**再借用**。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Point { x: 0, y: 0 }\n",
      "Point { x: 10, y: 10 }\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Point {\n",
    "    x: i32,\n",
    "    y: i32,\n",
    "}\n",
    "\n",
    "impl Point {\n",
    "    fn move_to(&mut self, x: i32, y: i32) {\n",
    "        self.x = x;\n",
    "        self.y = y;\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let mut p = Point { x: 0, y: 0 };\n",
    "    let r = &mut p; // 可变引用 `r` \n",
    "    let rr: &Point = &*r; // 不可变引用 `rr`; `rr` 是对 `r` 的再借用\n",
    "\n",
    "    println!(\"{:?}\", rr);\n",
    "    r.move_to(10, 10);\n",
    "    println!(\"{:?}\", r);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上代码，大家可能会觉得可变引用 `r` 和不可变引用 `rr` 同时存在会报错吧？但是事实上并不会，原因在于 `rr` 是对 `r` 的再借用。\n",
    "\n",
    "对于再借用而言，`rr` 再借用时不会破坏借用规则，但是你不能在它的生命周期内再使用原来的借用 `r`，来看看对上段代码的分析："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "{\n",
    "    let mut p = Point { x: 0, y: 0 };\n",
    "    let r = &mut p;\n",
    "    // reborrow! 此时对`r`的再借用不会导致跟上面的借用冲突\n",
    "    let rr: &Point = &*r;\n",
    "\n",
    "    // 再借用`rr`最后一次使用发生在这里，在它的生命周期中，我们并没有使用原来的借用`r`，因此不会报错\n",
    "    println!(\"{:?}\", rr);\n",
    "\n",
    "    // 再借用结束后，才去使用原来的借用`r`\n",
    "    r.move_to(10, 10);\n",
    "    println!(\"{:?}\", r);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 函数体内对参数的二次借用也是典型的 `Reborrow` 场景\n",
    "\n",
    "use std::vec::Vec;\n",
    "\n",
    "/// 传入一个可变借用 `&mut Vec<String>`，函数里只读取长度，不修改内容。\n",
    "fn read_length(strings: &mut Vec<String>) -> usize {\n",
    "    // 调用 `len()` 需要的是 `&Vec<String>`（不可变借用）。\n",
    "    // 编译器在这里会把现有的 `&mut Vec<String>` 自动“再借出”一个短生命周期的 `&Vec<String>`。\n",
    "    // 这个过程就是 reborrow：在 `len()` 调用期间，原来的可变借用被暂时冻结，\n",
    "    // 只有等 `len()` 返回后，`&mut` 的独占权限才会恢复。\n",
    "    strings.len()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot borrow `*r` as mutable because it is also borrowed as immutable",
     "output_type": "error",
     "traceback": [
      "    r.move_to(10, 10);",
      "\u001b[91m    ^^^^^^^^^^^^^^^^^\u001b[0m \u001b[94mmutable borrow occurs here\u001b[0m",
      "    let rr: &Point = &*r;",
      "\u001b[91m                     ^^^\u001b[0m \u001b[94mimmutable borrow occurs here\u001b[0m",
      "    println!(\"{:?}\", rr);",
      "\u001b[91m                     ^^\u001b[0m \u001b[94mimmutable borrow later used here\u001b[0m",
      "cannot borrow `*r` as mutable because it is also borrowed as immutable"
     ]
    }
   ],
   "source": [
    "// 破坏这条规则: 只需要在 rr 再借用的生命周期内使用一次原来的借用 r\n",
    "{\n",
    "    let mut p = Point { x: 0, y: 0 };\n",
    "    let r = &mut p;\n",
    "    let rr: &Point = &*r;\n",
    "\n",
    "    r.move_to(10, 10);\n",
    "\n",
    "    println!(\"{:?}\", rr);\n",
    "\n",
    "    println!(\"{:?}\", r);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生命周期消除规则补充"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### impl 块消除"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::io::{self, Read};\n",
    "\n",
    "/// 一个带生命周期参数的极简缓冲读取器。\n",
    "pub struct BufReader<'a, R> {\n",
    "    inner: &'a mut R,\n",
    "    buf: Vec<u8>,\n",
    "}\n",
    "\n",
    "/// 现代写法：演示匿名生命周期 `'_` 的 impl。\n",
    "pub trait Reader {\n",
    "    fn read_line(&mut self, line: &mut String) -> io::Result<usize>;\n",
    "}\n",
    "\n",
    "/// 旧写法：利用带名字的 `'a`，保留作对比。\n",
    "#[allow(dead_code)]\n",
    "pub trait ReaderLegacy {\n",
    "    fn read_line(&mut self, line: &mut String) -> io::Result<usize>;\n",
    "}\n",
    "\n",
    "impl<'a, R> BufReader<'a, R>\n",
    "where\n",
    "    R: Read,\n",
    "{\n",
    "    /// 方便外部创建 BufReader。\n",
    "    pub fn new(inner: &'a mut R) -> Self {\n",
    "        BufReader {\n",
    "            inner,\n",
    "            buf: Vec::new(),\n",
    "        }\n",
    "    }\n",
    "\n",
    "    fn read_line_inner(&mut self, line: &mut String) -> io::Result<usize> {\n",
    "        line.clear();\n",
    "        let mut temp = [0u8; 1];\n",
    "\n",
    "        while self.inner.read(&mut temp)? == 1 && temp[0] != b'\\n' {\n",
    "            line.push(temp[0] as char);\n",
    "        }\n",
    "\n",
    "        Ok(line.len())\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 旧写法：必须写出 `'a`\n",
    "#[allow(dead_code)]\n",
    "impl<'a, R> ReaderLegacy for BufReader<'a, R> // 生命周期参数也是类型的一部分\n",
    "where\n",
    "    R: Read,\n",
    "{\n",
    "    fn read_line(&mut self, line: &mut String) -> io::Result<usize> {\n",
    "        self.read_line_inner(line)\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "// 新写法：通过匿名生命周期 `'_` 消除 impl 块中的 `'a`\n",
    "impl<R> Reader for BufReader<'_, R>\n",
    "where\n",
    "    R: Read,\n",
    "{\n",
    "    fn read_line(&mut self, line: &mut String) -> io::Result<usize> {\n",
    "        self.read_line_inner(line)\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**匿名生命周期 `'_`**\n",
    "- 当 `impl` 块内部根本不需要直接使用某个生命周期参数时，可以用 `'_` 代替显式命名。这样写既简洁又能让读者知道“生命周期存在，但无需命名”。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生命周期约束消除"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// Rust 2015\n",
    "struct Ref<'a, T: 'a> {\n",
    "    field: &'a T\n",
    "}\n",
    "\n",
    "// Rust 2018\n",
    "struct Ref<'a, T> {\n",
    "    field: &'a T\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**结构体字段的生命周期约束自动推断**\n",
    "- 自 Rust 1.31（2018 edition）起，编译器会自动推断 `T: 'a` 类型约束，因此 `struct Ref<'a, T>` 中的字段 `&'a T` 不再需要手动添加 `T: 'a`。这让代码更干净、更易读。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## * 一个复杂的例子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot borrow `list` as immutable because it is also borrowed as mutable",
     "output_type": "error",
     "traceback": [
      "    use_list(&list);",
      "\u001b[91m             ^^^^^\u001b[0m \u001b[94mimmutable borrow occurs here\u001b[0m",
      "    list.get_interface().noop();",
      "\u001b[91m    ^^^^\u001b[0m \u001b[94mmutable borrow occurs here\u001b[0m",
      "    use_list(&list);",
      "\u001b[91m             ^^^^^\u001b[0m \u001b[94mmutable borrow later used here\u001b[0m",
      "cannot borrow `list` as immutable because it is also borrowed as mutable"
     ]
    }
   ],
   "source": [
    "struct Interface<'a> {\n",
    "    manager: &'a mut Manager<'a>\n",
    "}\n",
    "\n",
    "impl<'a> Interface<'a> {\n",
    "    pub fn noop(self) {\n",
    "        println!(\"interface consumed\");\n",
    "    }\n",
    "}\n",
    "\n",
    "struct Manager<'a> {\n",
    "    text: &'a str\n",
    "}\n",
    "\n",
    "struct List<'a> {\n",
    "    manager: Manager<'a>,\n",
    "}\n",
    "\n",
    "impl<'a> List<'a> {\n",
    "    pub fn get_interface(&'a mut self) -> Interface {\n",
    "        Interface {\n",
    "            manager: &mut self.manager\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut list = List {\n",
    "        manager: Manager {\n",
    "            text: \"hello\"\n",
    "        }\n",
    "    };\n",
    "\n",
    "    list.get_interface().noop();\n",
    "\n",
    "    println!(\"Interface should be dropped here and the borrow released\");\n",
    "\n",
    "    // 下面的调用会失败，因为同时有不可变/可变借用\n",
    "    // 但是Interface在之前调用完成后就应该被释放了\n",
    "    use_list(&list);\n",
    "}\n",
    "\n",
    "fn use_list(list: &List) {\n",
    "    println!(\"{}\", list.manager.text);\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "interface consumed\n",
      "Interface should be dropped here and the borrow released\n",
      "hello\n"
     ]
    }
   ],
   "source": [
    "struct Interface<'b, 'a: 'b> {\n",
    "    manager: &'b mut Manager<'a>\n",
    "}\n",
    "\n",
    "impl<'b, 'a: 'b> Interface<'b, 'a> {\n",
    "    pub fn noop(self) {\n",
    "        println!(\"interface consumed\");\n",
    "    }\n",
    "}\n",
    "\n",
    "struct Manager<'a> {\n",
    "    text: &'a str\n",
    "}\n",
    "\n",
    "struct List<'a> {\n",
    "    manager: Manager<'a>,\n",
    "}\n",
    "\n",
    "impl<'a> List<'a> {\n",
    "    pub fn get_interface<'b>(&'b mut self) -> Interface<'b, 'a>\n",
    "    where 'a: 'b {\n",
    "        Interface {\n",
    "            manager: &mut self.manager\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "\n",
    "    let mut list = List {\n",
    "        manager: Manager {\n",
    "            text: \"hello\"\n",
    "        }\n",
    "    };\n",
    "\n",
    "    list.get_interface().noop();\n",
    "\n",
    "    println!(\"Interface should be dropped here and the borrow released\");\n",
    "\n",
    "    // 下面的调用可以通过，因为Interface的生命周期不需要跟list一样长\n",
    "    use_list(&list);\n",
    "}\n",
    "\n",
    "fn use_list(list: &List) {\n",
    "    println!(\"{}\", list.manager.text);\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `&'static` 和 `T: 'static`\n",
    "\n",
    "- https://course.rs/advance/lifetime/static.html\n",
    "- https://practice-zh.course.rs/lifetime/static.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "TL;DR：`&'static` 与 `T: 'static`\n",
    "\n",
    "- **`&'static` 是针对引用本身的标注**：\n",
    "   只有当引用指向的数据能活到程序结束（通常是字面量或常量静态数据），这个引用才允许写成 `&'static T`。引用变量本身仍受作用域约束，出了作用域就不能再用了。\n",
    "- **`T: 'static` 是对类型参数（或 trait 对象）施加的生命周期约束**：\n",
    "   表示这个类型的值要么拥有 `'static` 生命周期，要么内部不含任何非 `'static` 的借用。\n",
    "   当泛型参数从未被“按值”使用、只以引用形式出现时，编译器不会强制检查它是否真的 `'static`，所以这个约束比 `&'static` 要宽松得多。\n",
    "- **`&'static` ≈ “这份引用指向的内存永远有效”**\n",
    "   **`T: 'static` ≈ “这个类型里不含短命借用”**\n",
    "   两者经常一起出现，但约束力度不同。\n",
    "- **实务经验**：\n",
    "  - 若你想通过加 `&'static` 来解错误，往往是在对使用生命周期建模时犯了设计错误，应优先重新理清所有权和借用。\n",
    "  - `T: 'static` 往往用来消除编译器抱怨，告诉它“别担心，这个值对后续生命周期来说足够长”。\n",
    "- **标准库用法对比**：`&'static` 出现 ~48 次，`T: 'static` 出现 ~112 次，说明连标准库也常靠它来满足借用检查器。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn main() {\n",
    "  let mark_twain: &str = \"Samuel Clemens\"; // 字符串字面值就具有 'static 生命周期\n",
    "  print_author(mark_twain);\n",
    "}\n",
    "\n",
    "fn print_author(author: &'static str) {\n",
    "  println!(\"{}\", author);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fmt::Display;\n",
    "\n",
    "fn main() {\n",
    "    let mark_twain = \"Samuel Clemens\";\n",
    "    print(&mark_twain);\n",
    "}\n",
    "\n",
    "fn print<T: Display + 'static>(message: &T) { // 'static 是作为生命周期约束来使用了\n",
    "    println!(\"{}\", message);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `&'static`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::{slice::from_raw_parts, str::from_utf8_unchecked};\n",
    "\n",
    "fn get_memory_location() -> (usize, usize) {\n",
    "  // “Hello World” 是字符串字面量，因此它的生命周期是 `'static`.\n",
    "  // 但持有它的变量 `string` 的生命周期就不一样了，它完全取决于变量作用域，对于该例子来说，也就是当前的函数范围\n",
    "  let string = \"Hello World!\";\n",
    "  let pointer = string.as_ptr() as usize;\n",
    "  let length = string.len();\n",
    "  (pointer, length)\n",
    "  // `string` 在这里被 drop 释放\n",
    "  // 虽然变量被释放，无法再被访问，但是数据依然还会继续存活\n",
    "}\n",
    "\n",
    "fn get_str_at_location(pointer: usize, length: usize) -> &'static str {\n",
    "  // 使用裸指针需要 `unsafe{}` 语句块\n",
    "  unsafe { from_utf8_unchecked(from_raw_parts(pointer as *const u8, length)) }\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "  let (pointer, length) = get_memory_location();\n",
    "  let message = get_str_at_location(pointer, length);\n",
    "  println!(\n",
    "    \"The {} bytes at 0x{:X} stored: {}\",\n",
    "    length, pointer, message\n",
    "  );\n",
    "  // 如果大家想知道为何处理裸指针需要 `unsafe`，可以试着反注释以下代码\n",
    "  // let message = get_str_at_location(1000, 10);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## * `T: 'static`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "`i` does not live long enough",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0597] Error:\u001b[0m `i` does not live long enough",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_7:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m12 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mi\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m5\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m         \u001b[38;5;68m┬\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m         \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m binding `i` declared here",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m14 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;37mp\u001b[0m\u001b[38;5;37mr\u001b[0m\u001b[38;5;37mi\u001b[0m\u001b[38;5;37mn\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m_\u001b[0m\u001b[38;5;37mi\u001b[0m\u001b[38;5;37mt\u001b[0m\u001b[38;5;37m(\u001b[0m\u001b[38;5;54m&\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;37m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m     \u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m┬\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;37m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m           \u001b[38;5;37m╰\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m argument requires that `i` is borrowed for `'static`",
      " \u001b[38;5;240m   │\u001b[0m               \u001b[38;5;54m│\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m               \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m borrowed value does not live long enough",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m16 │\u001b[0m \u001b[38;5;100m}\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;100m┬\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m `i` dropped here while still borrowed",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    },
    {
     "ename": "Error",
     "evalue": "`i` does not live long enough",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0597] Error:\u001b[0m `i` does not live long enough",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_7:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m12 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100mi\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m5\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m         \u001b[38;5;100m┬\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m         \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m binding `i` declared here",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m15 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mp\u001b[0m\u001b[38;5;68mr\u001b[0m\u001b[38;5;68mi\u001b[0m\u001b[38;5;68mn\u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68m_\u001b[0m\u001b[38;5;68mi\u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68m1\u001b[0m\u001b[38;5;68m(\u001b[0m\u001b[38;5;54m&\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;68m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m     \u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┬\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;68m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m           \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m argument requires that `i` is borrowed for `'static`",
      " \u001b[38;5;240m   │\u001b[0m                \u001b[38;5;54m│\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m                \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m borrowed value does not live long enough",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "use std::fmt::Debug;\n",
    "\n",
    "fn print_it<T: Debug + 'static>( input: T) {\n",
    "    println!( \"'static value passed in is: {:?}\", input );\n",
    "}\n",
    "\n",
    "fn print_it1( input: impl Debug + 'static ) {\n",
    "    println!( \"'static value passed in is: {:?}\", input );\n",
    "}\n",
    "\n",
    "{\n",
    "    let i = 5;\n",
    "\n",
    "    print_it(&i);\n",
    "    print_it1(&i);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'static value passed in is: 5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::fmt::Debug;\n",
    "\n",
    "fn print_it<T: Debug + 'static>( input: &T) {\n",
    "    println!( \"'static value passed in is: {:?}\", input );\n",
    "}\n",
    "\n",
    "{\n",
    "    let i = 5;\n",
    "\n",
    "    print_it(&i);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "`s1` does not live long enough",
     "output_type": "error",
     "traceback": [
      "    r3 = &s1;",
      "\u001b[91m         ^^^\u001b[0m \u001b[94mborrowed value does not live long enough\u001b[0m",
      "  }",
      "\u001b[91m  ^\u001b[0m \u001b[94m`s1` dropped here while still borrowed\u001b[0m",
      "    let s1 = \"String\".to_string();",
      "\u001b[91m        ^^\u001b[0m \u001b[94mbinding `s1` declared here\u001b[0m",
      "  println!(\"{}\", r3);",
      "\u001b[91m                 ^^\u001b[0m \u001b[94mborrow later used here\u001b[0m",
      "`s1` does not live long enough"
     ]
    }
   ],
   "source": [
    "use std::fmt::Display;\n",
    "\n",
    "{\n",
    "  let r1;\n",
    "  let r2;\n",
    "  {\n",
    "    static STATIC_EXAMPLE: i32 = 42;\n",
    "    r1 = &STATIC_EXAMPLE;\n",
    "    let x = \"&'static str\";\n",
    "    r2 = x;\n",
    "    // r1 和 r2 持有的数据都是 'static 的，因此在花括号结束后，并不会被释放\n",
    "  }\n",
    "\n",
    "  println!(\"&'static i32: {}\", r1); // -> 42\n",
    "  println!(\"&'static str: {}\", r2); // -> &'static str\n",
    "\n",
    "  let r3: &str;\n",
    "\n",
    "  {\n",
    "    let s1 = \"String\".to_string();\n",
    "\n",
    "    // s1 虽然没有 'static 生命周期，但是它依然可以满足 T: 'static 的约束\n",
    "    // 充分说明这个约束是多么的弱。。\n",
    "    static_bound(&s1);\n",
    "\n",
    "    // s1 是 String 类型，没有 'static 的生命周期，因此下面代码会报错\n",
    "    r3 = &s1;\n",
    "\n",
    "    // s1 在这里被 drop\n",
    "  }\n",
    "  println!(\"{}\", r3);\n",
    "}\n",
    "\n",
    "fn static_bound<T: Display + 'static>(t: &T) {\n",
    "  println!(\"{}\", t);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `static` 到底针对谁？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "大家有没有想过，到底是 `&'static` 这个引用还是该引用指向的数据活得跟程序一样久呢？\n",
    "\n",
    "**答案是引用指向的数据**，而引用本身是要遵循其作用域范围的，我们来简单验证下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot find value `static_string` in this scope",
     "output_type": "error",
     "traceback": [
      "    println!(\"static_string reference remains alive: {}\", static_string);",
      "\u001b[91m                                                          ^^^^^^^^^^^^^\u001b[0m \u001b[94mnot found in this scope\u001b[0m",
      "cannot find value `static_string` in this scope"
     ]
    }
   ],
   "source": [
    "{\n",
    "    {\n",
    "        let static_string = \"I'm in read-only memory\";\n",
    "        println!(\"static_string: {}\", static_string);\n",
    "\n",
    "        // 当 `static_string` 超出作用域时，该引用不能再被使用，但是数据依然会存在于 binary 所占用的内存中\n",
    "    }\n",
    "\n",
    "    println!(\"static_string reference remains alive: {}\", static_string);\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Rust",
   "language": "rust",
   "name": "rust"
  },
  "language_info": {
   "codemirror_mode": "rust",
   "file_extension": ".rs",
   "mimetype": "text/rust",
   "name": "rust",
   "pygment_lexer": "rust",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
